﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using TaskKernel.Configuration;
using TaskKernel.Domain;

namespace TaskKernel.DTO
{
    public static class DTOExtensions
    {
        public static IList<UniversalModelDDL> ToView(this IEnumerable<Department> departments)
        {
            var models = new List<UniversalModelDDL>();
            foreach (Department department in departments)
                models.Add(new UniversalModelDDL(department.UID, department.DepartmentName));
            return models;
        }

        public static List<UniversalModelDDL> ToViewWithEmptyValue(this IEnumerable<Account> accounts)
        {
            var models = new List<UniversalModelDDL>();
            models.Add(new UniversalModelDDL(Guid.Empty, "Не определен"));
            models.AddRange(accounts.ToView());
            return models;
        }

        public static List<UniversalModelDDL> ToView(this IEnumerable<Account> accounts)
        {
            var models = new List<UniversalModelDDL>();
            foreach (Account account in accounts)
            {
                if (account != null)
                    models.Add(new UniversalModelDDL(account.UID, account.FullName));
            }
            return models;
        }

        public static List<UniversalModelDDL> ToView(this IEnumerable<Template> tmplates)
        {
            var models = new List<UniversalModelDDL>();
            foreach (Template template in tmplates)
                models.Add(new UniversalModelDDL(template.UID, template.Name));
            return models;
        }

        public static ImageSet ConvertToImageSet(this Task task, Account account)
        {
            return new ImageSet
                       {
                        //   Exclamation = task.IsExpired(),
                           Reminder = task.HasReminderFor(account),
                        //   iamParticipant = task.HasParticipant(account)
                       };
        }

        public static ArchiveTaskListModel ConvertToArchiveTaskListModel(this Task task, Account account)
        {
            var literalHelper = new LiteralHelper();
            if (task.IsExpired()) literalHelper.SetFont(Color.Red);
            if (!task.IsReadBy(account)) literalHelper.SetBold();
            return
                new ArchiveTaskListModel(
                    task.Department.WebPath + TaskKernelConfiguration.SuffixPath + TaskKernelConfiguration.SeparatorPath + TaskKernelConfiguration.EditPage + task.UID,
                    literalHelper.Insert(Tools.ReduceStringBySize(task.TaskName, 80)),
                    task.Owner.FullName,
                    task.DateCreate,
                    task.DateClose,
                    task.DateLastHistoryEntry,
                    task.Executor == null ? "" : task.Executor.FullName,
                    task.Department.DepartmentName,
                    task.ConvertToImageSet(account),
                    task.Tag
                    );
        }

        public static TaskListInDepartmentModel ConvertToTaskListInDepartmentModel(this Task task, Account account)
        {
            var literalHelper = new LiteralHelper();
            if (task.IsExpired()) literalHelper.SetFont(Color.Red);
            if (!task.IsReadBy(account)) literalHelper.SetBold();
            return
                new TaskListInDepartmentModel(
                    task.Department.WebPath + TaskKernelConfiguration.SuffixPath + TaskKernelConfiguration.SeparatorPath + TaskKernelConfiguration.EditPage + task.UID,
                    literalHelper.Insert(Tools.ReduceStringBySize(task.TaskName, 80)),
                    task.Owner.FullName,
                    task.DateCreate,
                    task.DateExpiration,
                    task.DateLastHistoryEntry,
                    task.Priority.ToDescriptionString(),
                    task.PercentComplete.ToString(),
                    task.ConvertToImageSet(account),
                    task.Tag
                    );
        }

        public static TaskListForExecutorInAllDepModel ConvertToTaskListForExecutorInAllDepModel_Executor(
            this Task task, Account account)
        {
            var literalHelper = new LiteralHelper();
            if (task.IsExpired()) literalHelper.SetFont(Color.Red);
            if (!task.IsReadBy(account)) literalHelper.SetBold();
            return new TaskListForExecutorInAllDepModel(
                task.Department.WebPath + TaskKernelConfiguration.SuffixPath + TaskKernelConfiguration.SeparatorPath + TaskKernelConfiguration.EditPage + task.UID,
                literalHelper.Insert(Tools.ReduceStringBySize(task.TaskName, 80)),
                task.Owner.FullName,
                task.DateCreate,
                task.DateExpiration,
                task.DateLastHistoryEntry,
                task.Priority.ToDescriptionString(),
                task.PercentComplete.ToString(),
                task.Department.DepartmentName,
                task.ConvertToImageSet(account),
                task.Tag
                );
        }

        public static TaskListForExecutorInAllDepModel ConvertToTaskListForExecutorInAllDepModel_ParticipantOwner(
            this Task task, Account account)
        {
            var literalHelper = new LiteralHelper();
            if (task.IsExpired()) literalHelper.SetFont(Color.Red);
            if (!task.IsReadBy(account)) literalHelper.SetBold();
            return new TaskListForExecutorInAllDepModel(
                task.Department.WebPath + TaskKernelConfiguration.SuffixPath + TaskKernelConfiguration.SeparatorPath + TaskKernelConfiguration.EditPage + task.UID,
                literalHelper.Insert(Tools.ReduceStringBySize(task.TaskName, 80)),
                task.Executor == null ? "" : task.Executor.FullName,
                task.DateCreate,
                task.DateExpiration,
                task.DateLastHistoryEntry,
                task.Priority.ToDescriptionString(),
                task.PercentComplete.ToString(),
                task.Department.DepartmentName,
                task.ConvertToImageSet(account),
                task.Tag
                );
        }

        public static ExecutorsModel ConvertToExecutorsModelItemArchiveTaskPresenter(this IEnumerable<Task> tasks,
                                                                                     string fullNameExecutor,
                                                                                     Account account)
        {
            var taskListModels = new List<AbstractTaskList>();
            var _tasks = new List<Task>();
            _tasks.AddRange(tasks);
            foreach (Task task in _tasks)
                taskListModels.Add(task.ConvertToArchiveTaskListModel(account));
            return new ExecutorsModel(fullNameExecutor, taskListModels.Count, taskListModels);
        }

        public static ExecutorsModel ConvertToExecutorsModelItemAllTaskPresenter(this IQueryable<Task> tasks,
                                                                                 Expression<Func<Task, bool>> condition,
                                                                                 string fullNameExecutor,
                                                                                 Account account)
        {
            var taskListModels = new List<AbstractTaskList>();
            IQueryable<Task> filteredTasks = tasks.Where(condition);
            foreach (Task task in filteredTasks){
                try{
                    taskListModels.Add(task.ConvertToTaskListInDepartmentModel(account));
                }
                catch(Exception){
                    throw new NotImplementedException(@"В БД ""криво"" создана задача.");
                }
            }
            return new ExecutorsModel(fullNameExecutor, taskListModels.Count,
                                      taskListModels.OrderByDescending(x => x.Priority).ThenByDescending(
                                          x => x.DateCreate).AsEnumerable().ToList());
        }

        public static ExecutorsModel ConvertToCreateExecutorModelItemPersonTaskPresenter(this IEnumerable<Task> tasks,
                                                                                         string iAm, Account account)
        {
            var taskListModels = new List<AbstractTaskList>();
            switch (iAm)
            {
                case TaskKernelResources.IamExecutor:
                    foreach (Task task in tasks)
                        taskListModels.Add(task.ConvertToTaskListForExecutorInAllDepModel_Executor(account));
                    break;
                case TaskKernelResources.IamParticipant:
                case TaskKernelResources.IamOwner:
                    foreach (Task task in tasks)
                        taskListModels.Add(task.ConvertToTaskListForExecutorInAllDepModel_ParticipantOwner(account));
                    break;
                default:
                    break;
            }
            ;
            return new ExecutorsModel(iAm, taskListModels.Count,
                                      taskListModels.OrderByDescending(x => x.Priority).ThenByDescending(
                                          x => x.DateCreate).AsEnumerable().ToList());
        }

        public static List<HistoryModel> HistoryEntryToView(this Task task, bool systemMessage, out IList<HistoryModel> fileHistoryEntry)
        {
            var historyModels = new List<HistoryModel>();
            fileHistoryEntry = new List<HistoryModel>();
            foreach (AbstractTaskHistoryEntry entry in task.HistoryEntries)
            {
                switch (entry.TaskHistoryEntryType)
                {
                    case HistoryEntryType.Comment:
                        var historyComment = (CommentTaskHistoryEntry) entry;
                        historyModels.Add(HistoryEntryModelFromEntry(historyComment));
                        break;
                    case HistoryEntryType.File:
                        var historyFile = (FileTaskHistoryEntry) entry;
                        if (null != historyFile.File){
                            var fileModel = HistoryEntryModelFromEntry(task, historyFile, historyFile.File);
                            historyModels.Add(fileModel);
                            fileHistoryEntry.Add(fileModel);
                        }
                        break;
                    case HistoryEntryType.InvisibleSystemMessage:
                        var historyParticipant = (InvisibleSystemMessage)entry;
                        if(systemMessage)
                            historyModels.Add(HistoryEntryModelFromEntry(historyParticipant));
                        break;
                    default:
                        break;
                }
            }
            historyModels.Reverse();
            fileHistoryEntry = fileHistoryEntry.Reverse().ToList();
            return historyModels;
        }

        private static HistoryModel HistoryEntryModelFromEntry(Task task, FileTaskHistoryEntry entry, File file)
        {
            return new HistoryModel(entry.DateCreate,
                                    @"<a href='EditTask.aspx?ID=" + task.UID + "&FileID=" + file.UID +
                                    @"'><U><FONT color=#0000ff size=2>" + file.FileName + "</font></u></a>",
                                    entry.Owner == null ? "" : entry.Owner.FullName);
        }

        private static HistoryModel HistoryEntryModelFromEntry(CommentTaskHistoryEntry entry)
        {
            return new HistoryModel(entry.DateCreate, entry.Comment,
                                    entry.Owner == null ? "" : entry.Owner.FullName);
        }


        private static HistoryModel HistoryEntryModelFromEntry(InvisibleSystemMessage entry)
        {
            return new HistoryModel(entry.DateCreate, entry.Comment,
                                    entry.Owner == null ? "" : entry.Owner.FullName);
        }
    }
}